#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    BaseRestEditor(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    entry_=T_MONGO;

    listModel=new QStringListModel(this);
    ui->listView->setModel(listModel);

    tableModel=new TableModel(this);
    ui->tableView->setModel(tableModel);

    createMenu();
    updateListView();
}

Widget::~Widget()
{
    delete ui;
}

void Widget::updateMenu()
{
    if(!menu->isEmpty())
    {
        menu->disconnect();
        menu->clear();
    }

    if(isListViewActive())
    {
        menu->addAction(QStringLiteral("新类目... (F1)"),this,&Widget::newCategory);
        menu->addAction(QStringLiteral("编辑类目..."),this,&Widget::editCategory);
        menu->addSeparator();
        menu->addAction(QStringLiteral("删除类目"),this,&Widget::removeCategory);
        menu->addSeparator();
    }
    else if(isTableViewActive())
    {
        menu->addAction(QStringLiteral("新条目... (F2)"),this,&Widget::newItem);
        menu->addAction(QStringLiteral("编辑条目... (F3)"),this,&Widget::editItem);
        menu->addSeparator();
        menu->addAction(QStringLiteral("删除条目"),this,&Widget::removeItem);
        menu->addSeparator();
    }

    menu->addAction(QStringLiteral("更新列表 (F4)"),this,&Widget::updateListView);
    menu->addAction(QStringLiteral("更新视图 (F5)"),this,&Widget::updateTableView);
}

bool Widget::isListViewActive()
{
    QWidget *widget=focusWidget();
    if(!widget)
        return false;

    return ui->listView == qobject_cast<QListView*>(widget);
}

bool Widget::isTableViewActive()
{
    QWidget *widget=focusWidget();
    if(!widget)
        return false;

    return ui->tableView == qobject_cast<QTableView*>(widget);
}

void Widget::customKeyEvent(QKeyEvent *event)
{
    switch (event->key())
    {
    case Qt::Key_F1:
        newCategory();
        break;
    case Qt::Key_F2:
        newItem();
        break;
    case Qt::Key_F3:
        editItem();
        break;
    case Qt::Key_F4:
        updateListView();
        break;
    case Qt::Key_F5:
        updateTableView();
        break;
    }
}

void Widget::newCategory()
{
    AddCategory addCategory;
    connect(&addCategory,&AddCategory::addItem,
            this,&Widget::onAddCategory);
    if(addCategory.exec() == QDialog::Accepted)
        delayUpdateView(1);
}

void Widget::editCategory()
{
    QModelIndex index=ui->listView->currentIndex();
    if(!index.isValid())
        return;

    QString category=index.data().toString();
    if(!metaProperties.contains(category))
        return;

    AddCategory addCategory;
    addCategory.setItem(category,
                        metaProperties.value(category),
                        metaColumns.value(category));
    connect(&addCategory,&AddCategory::updateItem,
            this,&Widget::onUpdateCategory);
    if(addCategory.exec() == QDialog::Accepted)
        delayUpdateView(1);
}

void Widget::removeCategory()
{
    QModelIndex index=ui->listView->currentIndex();
    if(!index.isValid())
        return;

    QString category=index.data().toString();
    QJsonObject obj;
    obj.insert("category",category);

    QString url=QString(URL_DELETE).arg(TD_META);
    emit post(url,QJsonDocument(obj).toJson(QJsonDocument::Compact));
    delayUpdateView(1);
}

void Widget::newItem()
{
    if(selectCategory.isEmpty())
        return;

    QStringList properties=metaProperties.value(selectCategory);
    QStringList columns;
    if(!metaColumns.isEmpty())
        columns=metaColumns.value(selectCategory);
    else
        columns=QStringList();

    AddItem addItem(selectCategory);
    addItem.prepare(properties,columns);
    connect(&addItem,&AddItem::addItem,
            this,&Widget::onAddItem);
    if(addItem.exec() == QDialog::Accepted)
        delayUpdateView(2);
}

void Widget::editItem()
{
    if(selectCategory.isEmpty())
        return;

    QModelIndex index=ui->tableView->currentIndex();
    if(!index.isValid())
        return;

    QStringList properties=metaProperties.value(selectCategory);
    QStringList values;
    for (int i = 0; i < properties.size(); ++i) {
        values.append(sp_fetchString(index,i));
    }
    QStringList columns=metaColumns.value(selectCategory);

    AddItem addItem(selectCategory);
    addItem.setItem(properties,values,columns);
    connect(&addItem,&AddItem::updateItem,
            this,&Widget::onUpdateItem);
    if(addItem.exec() == QDialog::Accepted)
        delayUpdateView(2);
}

void Widget::removeItem()
{
    if(selectCategory.isEmpty())
        return;

    QModelIndex index=ui->tableView->currentIndex();
    if(!index.isValid())
        return;

    QStringList properties=metaProperties.value(selectCategory);
    QJsonObject obj;
    obj.insert("category",selectCategory);
    obj.insert(properties.at(0),sp_fetchString(index,0));

    QString url=QString(URL_DELETE).arg(selectCategory);
    emit post(url,QJsonDocument(obj).toJson(QJsonDocument::Compact));
    delayUpdateView(2);
}

void Widget::onAddCategory(const QJsonObject &object)
{
    QString url=QString(URL_INSERT).arg(TD_META);
    emit post(url,QJsonDocument(object).toJson(QJsonDocument::Compact));
}

void Widget::onUpdateCategory(const QJsonArray &array)
{
    QString url=QString(URL_UPDATE).arg(TD_META);
    emit post(url,QJsonDocument(array).toJson(QJsonDocument::Compact));
}

void Widget::onAddItem(const QJsonObject &object)
{
    if(selectCategory.isEmpty())
        return;

    QString url=QString(URL_INSERT).arg(selectCategory);
    emit post(url,QJsonDocument(object).toJson(QJsonDocument::Compact));
}

void Widget::onUpdateItem(const QJsonArray &array)
{
    if(selectCategory.isEmpty())
        return;

    QString url=QString(URL_UPDATE).arg(selectCategory);
    emit post(url,QJsonDocument(array).toJson(QJsonDocument::Compact));
}

void Widget::on_listView_doubleClicked(const QModelIndex &index)
{
    if(index.isValid())
    {
        selectCategory=index.data().toString();
        updateTableView();
    }
}

void Widget::delayUpdateView(int type)
{
    QEventLoop loop;
    QTimer::singleShot(200,&loop,&QEventLoop::quit);
    loop.exec();

    if(type==1)
        updateListView();
    else
        updateTableView();
}

void Widget::updateListView()
{
    if(listModel->rowCount() != 0)
        listModel->setStringList(QStringList());

    if(!metaProperties.isEmpty())
        metaProperties.clear();

    if(!metaColumns.isEmpty())
        metaColumns.clear();

    if(tableModel->rowCount() != 0)
        tableModel->clear();

    emit get(URL_META);
}

void Widget::updateTableView()
{
    if(selectCategory.isEmpty())
        return;

    if(tableModel->rowCount() != 0)
        tableModel->clear();

    QString url= QString(URL_ALL).arg(selectCategory);
    emit get(url);
}

void Widget::onReceivedObject(const QJsonObject &object)
{
    if(!object.contains("entry") || object.value("entry").toString() != entry_)
        return;

    if(object.contains(TD_META))
        processCategory(object.value(TD_META).toArray());
    else if(object.contains("detail"))
        processDetail(object.value("detail").toArray());
}

void Widget::processCategory(const QJsonArray &array)
{
    if(array.isEmpty())
        return;

    QStringList items;
    for(int i=0;i<array.size();i++)
    {
        QJsonObject obj=array.at(i).toObject();
        QString category=obj.value("category").toString();
        QStringList properties=Piv(obj.value("properties").toArray()).getStringList();
        items.append(category);
        metaProperties.insert(category,properties);
        if(obj.contains("columns"))
        {
            QStringList columns=Piv(obj.value("columns").toArray()).getStringList();
            if(columns.isEmpty())
                return;

            metaColumns.insert(category,columns);
        }
    }
    if(!items.isEmpty())
        listModel->setStringList(items);
}

void Widget::processDetail(const QJsonArray &array)
{
    if(array.isEmpty() || selectCategory.isEmpty())
        return;

    QStringList properties=metaProperties.value(selectCategory);
    QStringList columns;
    if(metaColumns.contains(selectCategory))
        columns=metaColumns.value(selectCategory);

    tableModel->setArray(array,properties,columns);
}
